#include "editor.h"
#include "QFile"
#include <QPainter>
#include <QTextBlock>
#include <QPainter>
#include <QPaintEvent>
#include <QScrollBar>

Editor::Editor(QWidget* parent) : QPlainTextEdit(parent) {
    _lineNumberArea = new LineNumberArea(this);
    setFont(QFont("Consolas", 18));
    setLineWrapMode(LineWrapMode::NoWrap);
    connect(this, &QPlainTextEdit::updateRequest, this, &Editor::updateLineNumberArea);
    connect(this, &QPlainTextEdit::blockCountChanged, this, &Editor::updateLineNumberAreaWidth);
    connect(this, &QPlainTextEdit::cursorPositionChanged, this, &Editor::unHighlightLine);
}

bool Editor::saveFile()
{
    QFile file(_fileName);
    if (!file.open(QIODeviceBase::WriteOnly)) {
        return false;
    }
    file.write(toPlainText().toUtf8());
    file.close();
}

void Editor::paintLineNumberArea(QPaintEvent *event)
{
    QPainter painter(_lineNumberArea);
    painter.setPen(QColor(174, 160, 160));
    painter.fillRect(event->rect(), QColor(240, 240, 240));

    auto block = firstVisibleBlock();
    int top = blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + blockBoundingRect(block).height();
    int blockNumber = block.blockNumber();

    while (block.isValid()) {
        painter.drawText(0, top, getLineNumberAreaWidth(), bottom - top, Qt::AlignCenter, QString::number(blockNumber + 1));
        top = bottom;
        bottom = top + blockBoundingRect(block).height();
        block = block.next();
        blockNumber++;
    }
}

void Editor::lineNumberMousePress(QMouseEvent* event)
{
    // 点击鼠标的位置/每块字体的高度 得到点击行号
    // event->position().y() / fontMetrics().height() 得到处于当前视口的行号
    // verticalScrollBar()->value() 得到视口相对于整个内容的垂直偏移量
    QTextBlock block = document()->findBlockByLineNumber(event->position().y() / fontMetrics().height() + verticalScrollBar()->value());
    setTextCursor(QTextCursor(block));
    this->highlightLine();
}

void Editor::resizeEvent(QResizeEvent *event)
{
    _lineNumberArea->setGeometry(0, 0, getLineNumberAreaWidth(), contentsRect().height());
    QPlainTextEdit::resizeEvent(event);
}

int Editor::getLineNumberAreaWidth()
{
    return 25 + QString::number(blockCount()).length() * fontMetrics().horizontalAdvance(QChar('a'));
}

void Editor::highlightLine()
{
    QList<QTextEdit::ExtraSelection> selections;

    QTextEdit::ExtraSelection select;
    select.format.setBackground(QColor(0, 120, 215));
    select.format.setForeground(QColor(255, 255, 255));
    select.format.setProperty(QTextTableFormat::FullWidthSelection, true);

    QTextCursor cursor = textCursor();
    cursor.select(QTextCursor::LineUnderCursor);
    select.cursor = cursor;

    selections.append(select);
    setExtraSelections(selections);
}

void Editor::updateLineNumberArea(const QRect &rect, int dy)
{
    if (dy) {
        _lineNumberArea->scroll(0, dy);
    } else {
        _lineNumberArea->update(0, rect.y(), getLineNumberAreaWidth(), rect.height());
    }
}

void Editor::updateLineNumberAreaWidth()
{
    setViewportMargins(getLineNumberAreaWidth(), 0, 0, 0);
}

void Editor::unHighlightLine()
{
    QList<QTextEdit::ExtraSelection> selections = extraSelections();
    selections.clear();
    setExtraSelections(selections);
}
